package org.luxor.cloud.gateway.component.route;

import com.baomidou.mybatisplus.core.toolkit.IdWorker;
import org.luxor.cloud.gateway.entity.GatewayRouteEntity;
import org.luxor.cloud.gateway.service.DynamicRouteService;
import org.springframework.cloud.gateway.handler.predicate.PredicateDefinition;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionRepository;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 基于JDBC存储的动态路由定义
 *
 * @author Mr.Yan  @date: 2020/10/30
 */
public class DynamicRouteDefinitionRepository implements RouteDefinitionRepository {

    private DynamicRouteService dynamicRouteService;

    public DynamicRouteDefinitionRepository(DynamicRouteService dynamicRouteService) {
        Assert.notNull(dynamicRouteService, "Spring容器中找不到[DynamicRouteService]的实例化对象!");
        this.dynamicRouteService = dynamicRouteService;
    }

    @Override
    public Mono<Void> save(Mono<RouteDefinition> route) {
        return route.flatMap(routeDefinition -> {
            List<PredicateDefinition> predicates = routeDefinition.getPredicates();
            if (CollectionUtils.isEmpty(predicates)) {
                return Mono.empty();
            }
            if (predicates.stream().anyMatch(p -> RouteTransform.PATH_ROUTE_PREDICATE_NAME.equals(p.getName()))) {
                return Mono.empty();
            }
            Long routeId = Long.parseLong(routeDefinition.getId());
            GatewayRouteEntity routeEntity = dynamicRouteService.getById(routeId);
            if (routeEntity == null) {
                routeDefinition.setId(IdWorker.getIdStr());
                dynamicRouteService.save(RouteTransform.toGatewayRouteEntity(routeDefinition));
            } else {
                dynamicRouteService.updateById(RouteTransform.toGatewayRouteEntity(routeDefinition));
            }
            return Mono.empty();
        });
    }

    @Override
    public Mono<Void> delete(Mono<String> routeId) {
        return routeId.flatMap(id -> {
            ArrayList<Long> ids = new ArrayList<>(2);
            ids.add(Long.parseLong(id));
            dynamicRouteService.removeByIds(ids);
            return Mono.empty();
        });
    }


    @Override
    public Flux<RouteDefinition> getRouteDefinitions() {
        Map<String, RouteDefinition> routs = dynamicRouteService.routeDefinitions();
        if (CollectionUtils.isEmpty(routs)) {
            return Flux.empty();
        }
        return Flux.fromIterable(routs.values());
    }


}
